package battleship;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.RenderingHints;
import java.util.List;
import java.util.Random;
import java.util.TreeSet;
import javax.swing.JButton;

/**
 *
 * @author Kamil
 */
@SuppressWarnings("serial")
public class Field extends JButton implements Comparable<Field>, Cloneable {

	public Integer row;
	public Integer col;
	public Coords coords;
	public FieldType fieldType = FieldType.NORMAL;
	public Random random = new Random();
	private String myLabel = null;

	public Field(int row, int col) {
		super();

		this.row = row;
		this.col = col;
		this.coords = null;

		setFocusPainted(false);
		setRolloverEnabled(false);
		setBorderPainted(false);
		setContentAreaFilled(false);

		setToolTipText("" + ((char) ('A' + row)) + (col + 1));
	}

	public void setMyLabel(String s) {
		this.myLabel = s;
	}

	public int getRow() {
		return row;
	}

	public int getCol() {
		return col;
	}

	public Field(int row, int col, Coords c) {
		this(row, col);
		this.coords = c;
	}

	@Override
	public void paintComponent(Graphics g) {
		Graphics2D g2d = (Graphics2D) g;
		Dimension dim = getSize();

		g2d.setColor(isEnabled() || fieldType == FieldType.SHIP ? fieldType.getColor() : FieldType.INACTIVE.getColor());
		g2d.fillRect(2, 2, dim.width - 2, dim.height - 2);

		if (myLabel != null) {
			RenderingHints rh = new RenderingHints(
					RenderingHints.KEY_ANTIALIASING,
					RenderingHints.VALUE_ANTIALIAS_ON);
			rh.put(RenderingHints.KEY_RENDERING,
					RenderingHints.VALUE_RENDER_QUALITY);
			g2d.setRenderingHints(rh);
			
			g2d.setColor(Color.BLACK);
			g2d.setFont(new Font("DejaVu Sans Mono", Font.BOLD, 13));
			g2d.drawString(myLabel, 8, 19);
		}

		//super.paintComponent(g);
	}

	public void changeType(FieldType f) {
		this.fieldType = f;
	}

	@Override
	public int compareTo(Field o) {
		if (row != o.row) {
			return row.compareTo(o.row);
		}
		return col.compareTo(o.col);
	}

	@Override
	public int hashCode() {
		return 100 * row + col;
	}

	@Override
	public Field clone() {
		return new Field(row, col);
	}

	@Override
	public boolean equals(Object obj) {
		if (obj == null) {
			return false;
		}
		if (getClass() != obj.getClass()) {
			return false;
		}
		final Field other = (Field) obj;
		if (this.row != other.row && (this.row == null || !this.row.equals(other.row))) {
			return false;
		}
		if (this.col != other.col && (this.col == null || !this.col.equals(other.col))) {
			return false;
		}
		return true;
	}

	@Override
	public String toString() {
		return "" + ((char) ('A' + row)) + (col + 1);
	}

	boolean isNeighbour(Field t) {
		int rowTemp = (getRow() - t.getRow());
		int colTemp = (getCol() - t.getCol());
		if (rowTemp < 0) {
			rowTemp = -rowTemp;
		}
		if (colTemp < 0) {
			colTemp = -colTemp;
		}
		if (rowTemp + colTemp != 1) {
			return false;
		}
		return true;
	}

	protected Field getUpper() {
		if (row > 0) {
			return ((Grid) getParent()).fields[row - 1][col];
		}
		return null;
	}

	protected Field getLower() {
		if (row + 1 < ((Grid) getParent()).rows) {
			return ((Grid) getParent()).fields[row + 1][col];
		}
		return null;
	}

	protected Field getLeft() {
		if (col > 0) {
			return ((Grid) getParent()).fields[row][col - 1];
		}
		return null;
	}

	protected Field getRight() {
		if (col + 1 < ((Grid) getParent()).cols) {
			return ((Grid) getParent()).fields[row][col + 1];
		}
		return null;
	}

	@SuppressWarnings("unchecked")
	protected TreeSet<Field> getReachable(TreeSet<Field> from, int ile, boolean curvedShipsAllowed) {
		Field t = this;
		Grid g = (Grid) t.getParent();
		if (!curvedShipsAllowed) {
			TreeSet<Field> fieldsInCol = new TreeSet<Field>();
			TreeSet<Field> fieldsInRow = new TreeSet<Field>();
			if (from.contains(t) == true) {
				fieldsInCol.add(t);
				fieldsInRow.add(t);
			}
			Field colField = t.getUpper();
			while (colField != null && from.contains(colField)) {
				fieldsInCol.add(colField);
				colField = colField.getUpper();
			}
			colField = t.getLower();
			while (colField != null && from.contains(colField)) {
				fieldsInCol.add(colField);
				colField = colField.getLower();
			}
			Field rowField = t.getLeft();
			while (rowField != null && from.contains(rowField)) {
				fieldsInRow.add(rowField);
				rowField = rowField.getLeft();
			}
			rowField = t.getRight();
			while (rowField != null && from.contains(rowField)) {
				fieldsInRow.add(rowField);
				rowField = rowField.getRight();
			}
			if (fieldsInRow.size() >= ile && fieldsInCol.size() >= ile) {
				if (random.nextBoolean()) {
					return fieldsInRow;
				} else {
					return fieldsInCol;
				}
			} else {
				if (fieldsInCol.size() >= ile) {
					return fieldsInCol;
				} else {
					return fieldsInRow;
				}
			}
		}
		TreeSet<Field> tempSet = (TreeSet) from.clone();
		TreeSet<Field> ret = new TreeSet<Field>();
		TreeSet<Field> queue = new TreeSet<Field>();
		Field act;
		if (tempSet.remove(t) == true) {
			queue.add(t);
		} else {
			for (Field f : g.getNeighbours(t)) {
				if (tempSet.contains(f)) {
					tempSet.remove(f);
					queue.add(f);
					break;
				}
			}
		}
		while (!queue.isEmpty()) {
			if (ile > 0 && ret.size() >= ile) {
				return ret;
			}
			act = queue.pollFirst();
			ret.add(act);
			for (Field f : g.getNeighbours(act)) {
				if (tempSet.contains(f)) {
					tempSet.remove(f);
					queue.add(f);
				}
			}
		}
		return ret;
	}

	public List<Field> getNeighboursWithCorners() {
		return ((Grid) getParent()).getNeighboursWithCorners(this);
	}

	public List<Field> getNeighbours() {
		return ((Grid) getParent()).getNeighbours(this);
	}
}
